﻿#region imports

using System;
using System.Diagnostics;
using System.Globalization;
using System.Web;
using System.Web.Routing;
using Microsoft.Data.Services.Toolkit;

#endregion

namespace Codeplex.ODataTFS.Web
{
	public class Global : HttpApplication
	{

		protected void Application_Error(object sender, EventArgs e)
		{
			var lastError = Server.GetLastError();

			Trace.TraceError(lastError.ToString());
		}

		protected void Application_BeginRequest(object sender, EventArgs e)
		{
			var requestPath = Request.AppRelativeCurrentExecutionFilePath;
			if (requestPath.Equals("~/", StringComparison.OrdinalIgnoreCase))
			{
				HttpContext.Current.Server.Transfer("~/Default.aspx");
			}

			//TODO: Investigate below

			var queryString = Request.QueryString;
			if (requestPath.EndsWith("Builds", StringComparison.InvariantCultureIgnoreCase))
			{
				string filterParameter = queryString.Get("$filter");
				if (!string.IsNullOrEmpty(filterParameter))
				{
					var filtersByProject = FiltersByProperties(filterParameter, "Project");
					var filtersByDefinition = FiltersByProperties(filterParameter, "Definition");
					var filtersByNumber = FiltersByProperties(filterParameter, "Number");
					var filtersByNonKeyAttributes = FiltersByProperties(filterParameter, "Reason", "Quality", "Status", "RequestedBy", "RequestedFor", "LastChangedBy", "StartTime", "FinishTime", "LastChangedOn", "BuildFinished", "DropLocation", "Errors", "Warnings");
					if ((filtersByProject || filtersByDefinition || filtersByNumber) && (!filtersByProject || !filtersByDefinition || !filtersByNumber) && !filtersByNonKeyAttributes)
					{
						Response.RedirectPermanent(string.Format(CultureInfo.InvariantCulture, "{0}{1} and StartTime ne datetime'0001-01-01T00:00:00.000'", Request.Url.LocalPath, Request.Url.Query));
					}
				}
			}
			else if (requestPath.EndsWith("Changes", StringComparison.InvariantCultureIgnoreCase))
			{
				var filterParameter = queryString.Get("$filter");
				if (!string.IsNullOrEmpty(filterParameter))
				{
					var filtersByChangeset = FiltersByProperties(filterParameter, "Changeset");
					var filtersByPath = FiltersByProperties(filterParameter, "Path");
					var filtersByNonKeyAttributes = FiltersByProperties(filterParameter, "Collection", "ChangeType", "Type");
					if ((filtersByChangeset ^ filtersByPath) && !filtersByNonKeyAttributes)
					{
						Response.RedirectPermanent(string.Format(CultureInfo.InvariantCulture, "{0}{1} and Collection ne ''", Request.Url.LocalPath, Request.Url.Query));
					}
				}
			}
		}

		private bool FiltersByProperties(string filter, params string[] fields)
		{
			foreach (var fieldName in fields)
			{
				if (filter.Contains(fieldName))
				{
					int nextFieldPos = filter.IndexOf(fieldName, 0, StringComparison.OrdinalIgnoreCase);
					while (nextFieldPos >= 0)
					{
						var literalValue = false;
						var nextQuoteStringPos = filter.IndexOf('\'', 0);
						while (nextQuoteStringPos >= 0 && nextQuoteStringPos < nextFieldPos)
						{
							literalValue = !literalValue;
							nextQuoteStringPos = filter.IndexOf('\'', nextQuoteStringPos + 1);
						}

						if (!literalValue)
						{
							return true;
						}

						nextFieldPos = filter.IndexOf(fieldName, nextFieldPos + 1, StringComparison.OrdinalIgnoreCase);
					}
				}
			}

			return false;
		}

		private void Application_Start(object sender, EventArgs e)
		{
			RouteTable.Routes.AddDataServiceRoute<TFSService>();
		}
	}
}
